﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Modules.Project.Comparers;
using Modules.Project.Entitys;
using Modules.System.User;
using PetaPoco;
using Pipelines.Sockets.Unofficial.Arenas;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Caching;
using PmSoft.DBContext;
using PmSoft.Entity;
using PmSoft.Repositories;
using PmSoft.Utilities;
using System;
using System.Linq;

namespace Modules.Project.Repositories
{
    [UseDI(ServiceLifetime.Scoped)]
    public class ProjectCorpRepository : Repository<ProjectCorp, DefaultDbContext>
    {
        private readonly ILogger logger;
        private readonly IApplicationContext applicationContext;
        private static readonly ProjectCorpComparer comparer = new();

        public ProjectCorpRepository(DefaultDbContext dbContext, IApplicationContext applicationContext, ILogger<ProjectCorpRepository> logger)
            : base(dbContext, applicationContext)
        {
            this.logger = logger;
            this.applicationContext = applicationContext;
        }

        /// <summary>
        /// 批量创建或更新
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="inProjectCorps"></param>
        public void CreateOrUpdate(int projectId, IEnumerable<ProjectCorp> inProjectCorps)
        {
            var dbProjectCorps = DbContext.Fetch<ProjectCorp>("WHERE project_id=@0", projectId);
            var itemsToDelete = dbProjectCorps.Except(inProjectCorps, comparer).ToList();
            foreach (var item in itemsToDelete)
            {
                Delete(item);
            }
            var itemsToUpdate = dbProjectCorps.Intersect(inProjectCorps, comparer).ToList();
            foreach (var item in itemsToUpdate)
            {
                var updateItem = inProjectCorps.FirstOrDefault(m => comparer.Equals(m, item));
                if (updateItem == null)
                    continue;
                updateItem.Id = item.Id;
                Update(updateItem);
            }
            var itemsToAdd = inProjectCorps.Except(dbProjectCorps, comparer).ToList();
            foreach (var item in itemsToAdd)
            {
                item.ProjectId = projectId;
                Insert(item);
            }
        }

        public bool ExistsByProjectCorp(ProjectCorp projectCorp)
        {
            return DbContext.Exists<ProjectCorp>("project_id=@0 AND corp_id=@1", projectCorp.ProjectId, projectCorp.CorpId);
        }

        public bool ExistsProjectCorp(int projectId, int corpId, 项目参建单位类型 role)
        {
            return DbContext.Exists<ProjectCorp>("project_id=@0 AND corp_id=@1 and role=@2", projectId, corpId, role);
        }

        public bool ExistsByProjectCorp(ProjectCorp projectCorp, int id)
        {
            return DbContext.Exists<ProjectCorp>("project_id=@0 AND corp_id=@1 and role=@2 AND id!=@3", projectCorp.ProjectId, projectCorp.CorpId, projectCorp.Role, id);
        }

        public IPagedList<ProjectCorp> GetProjectCorps(ProjectCorpQuery query, int pageNum, int pageSize)
        {
            Sql sql = Sql.Builder;
            sql.Select("project_corp.id")
                .From("project_corp");
            sql.InnerJoin("project as b").On("project_corp.project_id=b.project_id and b.is_deleted=0");
            // sql.LeftJoin("corp as c").On("project_corp.corp_id=c.corp_id and role!=@0", 项目参建单位类型.建设单位);
            //sql.LeftJoin("constructor as d").On("project_corp.corp_id=d.constructor_id and role=@0", 项目参建单位类型.建设单位);

            #region 主管单位数据权限

            if (applicationContext.CurrentUser is IDeptUser deptUser && !deptUser.IsSuperAdministrator())
            {
                sql.InnerJoin("project as prj").On($"project_corp.project_id=prj.project_id and prj.is_deleted=0 and prj.industry_type=@0 ", deptUser.IndustryType);
                if (deptUser.Level == AdministrativeLevel.City)
                    sql.Append($" and prj.city_code={deptUser.CityCode}");
                if (deptUser.Level == AdministrativeLevel.Area)
                    sql.Append($" and prj.area_code={deptUser.AreaCode}");
            }

            #endregion 主管单位数据权限

            if (!string.IsNullOrWhiteSpace(query.Keywords))
                sql.Where("(b.name like @0 or c.name like @0 or d.name like @0)", "%" + StringUtility.StripSQLInjection(query.Keywords) + "%");
            if (query.ProjectId.HasValue)
                sql.Where("project_corp.project_id=@0", query.ProjectId);
            if (query.CorpId.HasValue)
                sql.Where("project_corp.corp_id=@0", query.CorpId);
            sql.OrderBy("project_corp.create_time DESC");
            return GetPagingEntities(pageSize, pageNum, sql);
        }

        public IEnumerable<ProjectCorp> GetProjectCorpsByCorpId(int corpId)
        {
            int areaVersion = EntityCacheService.GetAreaVersion("CorpId", corpId);
            return GetTopEntities(1000, CachingExpirationType.ObjectCollection, () =>
            {
                return $"ProjectCorpsByCorpId:{corpId}:{areaVersion}";
            }, () =>
            {
                Sql sql = Sql.Builder
                .Select("id")
                .From("project_corp")
                .Where("corp_id=@0", corpId);
                return sql;
            });
        }

        public IEnumerable<ProjectCorp> GetProjectCorpsByProjectId(int projectId)
        {
            int areaVersion = EntityCacheService.GetAreaVersion("ProjectId", projectId);
            return GetTopEntities(1000, CachingExpirationType.ObjectCollection, () =>
            {
                return $"ProjectCorpsByProjectId:{projectId}:{areaVersion}";
            }, () =>
            {
                Sql sql = Sql.Builder
                .Select("id")
                .From("project_corp")
                .Where("project_id=@0", projectId);
                return sql;
            });
        }

        public IEnumerable<ProjectCorp> GetProjectCorpsByProjectCorpIds(IEnumerable<int> projectCorpIds)
        {
            if (projectCorpIds == null || projectCorpIds.Count() == 0)
                return Enumerable.Empty<ProjectCorp>();
            Sql sql = Sql.Builder;
            sql.Select("id")
                .From("project_corp");
            if (projectCorpIds.Count() > 0)
                sql.Where("id in(@0)", projectCorpIds);
            var ids = DbContext.FetchFirstColumn<int>(sql);

            return PopulateEntitiesByEntityIds(ids);
        }

        //public ProjectCorp? GetProjectCorpByProjectIdAndCorpId(int projectId, int corpId, 项目参建单位类型? role)
        //{
        //    Sql sql = Sql.Builder.Select("id").From("project_corp").Where("project_id=@0 AND corp_id=@1", projectId, corpId);
        //    if (role.HasValue)
        //    {
        //        sql.Where("role = @0", role.Value);
        //    }
        //    var id = DbContext.FirstOrDefault<int>(sql);
        //    if (id == 0)
        //        return null;
        //    return Get(id);
        //}

        /// <summary>
        /// author:hzj date:2023/11/14 describe:根据查询条件获取所有项目参建企业
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public IEnumerable<ProjectCorp> GetProjectCorpsByProjectIdCorpId(ProjectCorpQuery query)
        {
            Sql sql = Sql.Builder;
            sql.Select("id")
                .From("project_corp");
            if (query.ProjectId.HasValue)
                sql.Where("project_id=@0", query.ProjectId);
            if (query.CorpId.HasValue)
                sql.Where("corp_id=@0", query.CorpId);
            if (query.Role.HasValue)
                sql.Where("role=@0", query.Role);
            sql.OrderBy("create_time DESC");
            var ids = DbContext.FetchFirstColumn<int>(sql);
            return PopulateEntitiesByEntityIds(ids);
        }
    }
}